using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Krile.Kernel.Bridges;

namespace Krile.Subsystem
{
    /// <summary>
    /// Debugging Agent
    /// </summary>
    internal static class Debugger
    {
        private static object repLocker = new object();
        private static List<DebugReport> reports = new List<DebugReport>();

        internal static void AddReport(DebugReport rep)
        {
            if (Core.Config != null && Core.Config.Security.Ignores != null)
            {
                foreach (var i in Core.Config.Security.Ignores)
                {
                    if (i.IsIgnoreReport(rep))
                        return;
                }
            }
            if (Core.Config != null &&
                Core.Config.Security.IgnoreNetworkError &&
                rep.IsExceptionReport &&
                rep.Exception != null &&
                rep.Exception is System.Net.WebException)
            {
                if (Core.FormManager != null && Core.FormManager.MainForm != null)
                    Core.FormManager.MainForm.SetBackStatusText(rep.Message);
            }
            else
            {
                lock (repLocker)
                {
                    reports.Add(rep);
                }
                if (Core.FormManager != null && Core.FormManager.MainForm != null)
                    Core.FormManager.MainForm.UpdateInfobar();
            }
        }

        internal static void AddReport(Exception excp)
        {
            AddReport(new DebugReport(excp));
        }

        internal static void AddReport(string msg)
        {
            AddReport(new DebugReport(msg));
        }

        internal static void Assert(bool expression, string message)
        {
            if (!expression)
                throw new KrileStrictCheckException(message);
        }

        internal static void WriteReport(bool onlyDisaster)
        {
            StringBuilder writeStr = new StringBuilder();
            if (reports.Count > 0)
            {
                writeStr.AppendLine("(Krile v." + Define.VersionString + "-" + Define.Build + ")");
                lock (repLocker)
                {
                    foreach (var rp in reports)
                    {
                        if (onlyDisaster && rp.Priority != DebugReport.Priorities.Fatal)
                            continue;
                        writeStr.AppendLine("> " + rp.DateTime + " - PR:" + rp.Priority.ToString());
                        writeStr.AppendLine(" MSG:" + rp.Message);
                        if (rp.IsExceptionReport)
                        {
                            writeStr.AppendLine(" @Exception Report---");
                            writeStr.AppendLine(rp.Exception.ToString());
                        }
                        writeStr.AppendLine();
                    }
                }
            }
            if (writeStr.ToString() != "")
            {
                var dest = Path.Combine(Define.AppPath, Define.DebugReportFileName);
                using (StreamWriter sw = new StreamWriter(dest, true))
                {
                    sw.WriteLine(writeStr.ToString());
                }
                var fi = new FileInfo(dest);
                if (fi.Length > Define.ReportSendLength && !String.IsNullOrEmpty(Define.DebugAgentFileName) && File.Exists(Path.Combine(Define.AppPath, Define.DebugAgentFileName)))
                    System.Diagnostics.Process.Start(Path.Combine(Define.AppPath, Define.DebugAgentFileName));
            }
        }

        internal static void ClearReports()
        {
            lock (repLocker)
            {
                reports.Clear();
            }
            if (Core.FormManager != null && Core.FormManager.MainForm != null)
                Core.FormManager.MainForm.UpdateInfobar();
        }

        internal static DebugReport[] GetReports()
        {
            lock (repLocker)
            {
                var ret = reports.ToArray();
                reports.Clear();
                if (Core.FormManager != null && Core.FormManager.MainForm != null)
                    Core.FormManager.MainForm.UpdateInfobar();
                return ret;
            }
        }

        internal static void SetReports(DebugReport[] reps)
        {
            lock (repLocker)
            {
                reports.Clear();
                if (reps != null)
                    reports.AddRange(reps);
            }
            if (Core.FormManager != null && Core.FormManager.MainForm != null)
                Core.FormManager.MainForm.UpdateInfobar();
        }

        internal static int GetReportLength()
        {
            return reports.Count;
        }
    }

    public class __DebugBridge : IDebugReporter
    {
        public void AddReport(DebugReport report)
        {
            Debugger.AddReport(report);
        }

        public void AddReport(Exception excp)
        {
            Debugger.AddReport(excp);
        }

        public void AddReport(string reportstr)
        {
            Debugger.AddReport(reportstr);
        }
    }
}
